package com.easycoding.framework.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.easycoding.framework.config.AppConfigHelper;
import com.easycoding.framework.config.AppConfigKey;
import com.easycoding.framework.exception.AppException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
 * <b>Description</b>:文件上传工具类<br/>
 * <b>Create Date</b>: 2007-8-20<br/>
 * <b>Version</b>: Since JDK 1.6.0<br/>
 * <b>Package</b>: com.easycoding.framework.util
 */
public class UploadFileUtil
{
	protected static Log log = LogFactory.getLog(UploadFileUtil.class);	
	private static SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
	//如aaa.jpg生成一张min_aaa.jpg
	/**
	 * 保存用户的上传文件
	 * @param userName 上传文件的用户的用户名
	 * @param file 上传文件的文件域,对应的临时文件
	 * @param fileName 上传文件的文件名
	 * @return 保存后相对于根目录的相对路径和文件名
	 * @throws BaseException 
	 */
	public static String saveUploadFile(String userName,File fromFile,String fileName) throws AppException
	{
		if(userName == null || userName.equals(""))
			userName = "myWeb";
		if(fromFile == null || !fromFile.exists() || fileName == null)
			return "";
		String absPath = "";
		StringBuffer sb = new StringBuffer();
		try
		{
			String webPath = System.getProperty("webapp.root");
			String userUploadDir = AppConfigHelper.getValue(AppConfigKey.USER_UPLOAD_DIR.getKey());
			sb.append(webPath).append("/").append(userUploadDir).append("/");
			sb.append(getMonthPath(new Date())).append("/").append(getUserPath(userName)).append("/");
			absPath += sb.toString();
			File newFile = new File(absPath);
			if(!newFile.exists())
				newFile.mkdirs();//创建此抽象路径名指定的目录，包括创建必需但不存在的父目录
			String newName = getUUIDFileName(fileName);
			absPath += newName;
			File toFile = new File(newFile,newName);
			if(!toFile.exists())
				toFile.createNewFile();
			copy(fromFile,toFile);
			return sb.append(newName).toString();
		}
		catch(Exception e)
		{
			if(log.isDebugEnabled())
				log.debug("保存用户上传文件时发生异常!path:"+absPath,e);
			throw new AppException("保存用户上传文件时发生异常",e);
		}
	}
	/**
	 * 保存用户的上传文件,如果是图片文件,还在相同目录下生成缩略图,如1.jpg,则小图为1_min.jpg
	 * @param userName 上传文件的用户的用户名
	 * @param file 上传文件的文件域,对应的临时文件
	 * @param fileName 上传文件的文件名
	 * @param width 生成缩略图的宽度
	 * @param height 生成缩略图的高度
	 * @return 保存后相对于根目录的相对路径和文件名
	 * @throws BaseException 
	 */
	public static String saveUploadFileCanBuildImg(String userName,File fromFile,String fileName,int width,int height) throws AppException
	{
		if(userName == null || userName.equals(""))
			userName = "myWeb";
		String absPath = "";
		StringBuffer sb = new StringBuffer();
		try
		{
			String webPath = System.getProperty("webapp.root");
			String userUploadDir = AppConfigHelper.getValue(AppConfigKey.USER_UPLOAD_DIR.getKey());
			sb.append(webPath).append("/").append(userUploadDir).append("/");
			sb.append(getMonthPath(new Date())).append("/").append(getUserPath(userName)).append("/");
			absPath += sb.toString();
			File newFile = new File(absPath);
			if(!newFile.exists())
				newFile.mkdirs();//创建此抽象路径名指定的目录，包括创建必需但不存在的父目录
			String newName = getUUIDFileName(fileName);
			absPath += newName;
			//System.out.println(absPath);
			File toFile = new File(newFile,newName);
			if(!toFile.exists())
				toFile.createNewFile();
			copy(fromFile,toFile);
			createSmallImage(toFile,width,height);
			return sb.append(newName).toString();
		}
		catch(Exception e)
		{
			if(log.isDebugEnabled())
				log.debug("保存用户上传文件时发生异常!path:"+absPath,e);
			throw new AppException("保存用户上传文件时发生异常",e);
		}
	}

	private static void createSmallImage(File theFile,int width,int height)
		throws Exception
	{
		//不能读取的图片文件,没办法生成小图
		if(PictureFormat.getFormatInFile(theFile) == null)
			return;
		Image src = javax.imageio.ImageIO.read(theFile);// 构造Image对象
		BufferedImage tag = new BufferedImage(width,height,
			BufferedImage.TYPE_INT_RGB);
		tag.getGraphics().drawImage(src,0,0,width,height,null); // 绘制缩小后的图
		String _filename = theFile.getName();
		FileOutputStream out = new FileOutputStream(theFile.getParent() + "/"
			+ getSmallName(_filename)); // 输出到文件流
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(tag); // 近JPEG编码
		out.close();
	}
	/**
	 * 根据给定的文件名得到小图的文件名
	 * @param name 原始文件名
	 * @return 小图文件名
	 */
	private static String getSmallName(String name)
	{
		int posi = name.lastIndexOf(".");
		if(posi < 0)
		{
			return name + AppConfigHelper.getValue(AppConfigKey.SMALL_IMAGE_FLAG.getKey());
		}
		else
		{
			return name.substring(0,posi) + AppConfigHelper.getValue(AppConfigKey.SMALL_IMAGE_FLAG.getKey())
				+ name.substring(posi,name.length());
		}
	}
	/**
	 * 根据给定的文件名,生成UUID文件名
	 * @param fileName 原始文件名
	 * @return UUID文件名
	 */
	private static String getUUIDFileName(String fileName)
	{
		if(fileName==null || fileName.equals(""))
			return "";
		int lastPosi = fileName.lastIndexOf(".");
		String fileType = "";
		if(lastPosi > 0)
		{
			fileType = fileName.substring(lastPosi,fileName.length());
		}
		return UUID.randomUUID()+fileType;
	}
	/**
	 * 得到给定日期的年月目录名称
	 * @param date 指定的日期
	 * @return 年月目录名称
	 */
	private static String getMonthPath(Date date)
	{
		return format.format(date);
	}
	/**
	 * 得到系统设定的上传目录的文件系统的绝对路径
	 * @param request 用户请求
	 * @return 设定的上传目录的文件系统的绝对路径
	 */
	@SuppressWarnings("unused")
	private static String getSystemUploadPath()
	{
		StringBuffer sb = new StringBuffer();
		String webPath = System.getProperty("webapp.root");
		String userUploadDir = AppConfigHelper.getValue(AppConfigKey.USER_UPLOAD_DIR.getKey());
		sb.append(webPath).append("/").append(userUploadDir).append("/");
		return sb.toString();
	}
	/**
	 * 返回应用的根目录的文件系统的绝对路径
	 * @param request 用户请求
	 * @return 根目录的文件系统的绝对路径
	 */
	@SuppressWarnings("unused")
	private static String getRootPath(HttpServletRequest request)
	{
		String temp = request.getSession().getServletContext().getRealPath("/");
		temp = temp.replaceAll("\\\\","/");
		if(!temp.endsWith("/"))
			temp += "/";		
		return temp;
	}
	/**
	 * 生成用户上传文件的自己的相对路径
	 * @param userName 用户名
	 * @return 用户上传文件的自己的相对路径
	 */
	private static String getUserPath(String userName)
	{
		//得到用户名的拼音
		userName = CnToSpell.getFullSpell(userName);
		StringBuffer sb = new StringBuffer();
		if(userName.length()<=2)
			sb.append(userName);
		if(userName.length()<=5)
		{
			sb.append(userName.substring(0,2)).append("/").append(userName.substring(2,userName.length())).append("/").append(userName);
		}
		else
		{
			sb.append(userName.substring(0,2)).append("/").append(userName.substring(2,5)).append("/").append(userName.substring(5)).append("/").append(userName);
		}
		return sb.toString();
	}
	/**
	 * 把上传文件从临时文件夹拷贝到指定的文件夹
	 * @param from 临时文件夹中的文件
	 * @param to 要生成的文件
	 */
	private static boolean copy(File from,File to) throws FileNotFoundException,IOException
	{
		boolean flag = false;
		if(from.exists()&&to.exists())
		{
			FileChannel fromChannel = null;
			FileChannel toChannel = null;
			try
			{
				fromChannel = (new FileInputStream(from)).getChannel();
				toChannel = (new FileOutputStream(to)).getChannel();
				fromChannel.transferTo(0,fromChannel.size(),toChannel);
				flag = true;
			}
			catch(FileNotFoundException e)
			{
				throw e;
			}
			catch(IOException e)
			{
				throw e;
			}
			finally
			{
				if(fromChannel != null)
				{
					fromChannel.close();
				}
				if(toChannel != null)
				{
					toChannel.close();
				}
			}
		}
		return flag;
	}
}
